package com.rogers.rmcdouga.skirmishgadget.client;

import java.util.List;

import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.event.dom.client.LoadEvent;
import com.google.gwt.event.dom.client.LoadHandler;
import com.google.gwt.gen2.logging.shared.Log;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.widgetideas.graphics.client.GWTCanvas;
import com.rogers.rmcdouga.skirmishgadget.client.java.awt.Dimension;
import com.rogers.rmcdouga.skirmishgadget.client.java.awt.Point;
import com.rogers.rmcdouga.skirmishgadget.client.java.awt.geom.Dimension2D;

public class Token {
	// Constants
	
	
	// Properties
	private Image image;				// Image to be displayed as the token
	private Point location;				// location of the top left corner of the token image
	private Dimension size;				// size of the token in feet - usually 5x5
	private BattleMap map;				// Map on which the token is located
	private String selectedBy = null;	// Is this token currently selected?

	private Token(Point location, Dimension size, String imageUrl, BattleMap map) {
		super();
		Log.info("Inside Token constructor - location = " + location.x + "," + location.y + "; imageUrl = '" + imageUrl + "'.");
		// Initialize the non-image parms
		this.map = map;
		this.location = location;
		this.size = size;
		
		// Gotta make anything to be used in the LoadHandler() final.
		this.image = new Image();
		final Token myToken = this;
		final List<Token> myList = map.getTokenList();
		final GWTCanvas myCanvas = map.getHtmlCanvas();
		final Point myLocation = location;
		this.image.addLoadHandler(new LoadHandler()
			{
				// Load handler does all the stuff we need to do after the image data has been retrieved by the browser,
				// for example, the Canvas DrawImage call cannot be made before the image data has been loaded.
				public void onLoad(LoadEvent event) {
					Log.info("Inside Token Image Load event handler");
					myList.add(myToken);
					draw();
				}
				
			}
			);
		
		this.image.setUrl(imageUrl);
		// Do to a bug in GWT (http://code.google.com/p/google-web-toolkit/issues/detail?id=863), images are not loaded
		// until they are attached to the DOM, so we need to add the image into an invisible container/
		RootPanel.get(map.invisibleImageContainerName).add(this.image);
	}
	
	private Token(String url, BattleMap map) {
		// create s default 1 square size Token.
		this(map.ORIGIN, new Dimension(map.squareSizeInFeet,map.squareSizeInFeet), url, map);
	}

	public static void CreateToken(Point location, String url, BattleMap map)
	{
		Token t = new Token(location, new Dimension(5,5), url, map);
	}
	
	public static void CreateToken(Point location, Dimension size, String url, BattleMap map)
	{
		Token t = new Token(location, size, url, map);
	}

	public void move(Point newLocation)
	{
		// TODO:  This is a brute force approach (redraw the whole map).  At some point we'll change this
		// to just refresh the spot where the token was and redraw just the token.
		// TODOL Eventually add some animation in here but for now, just jump the token.
//		map.refresh(location, size);	// erase old location
		location = newLocation;
//		draw();
		map.redraw(); 	// brute force
	}
	public void draw()
	{
		Log.info("Inside Token draw routine: zoom=" + map.getZoomLevel() + ".");
		Log.info("Inside Token draw routine: image Size=" + image.getWidth() + "," + image.getHeight() + ".");
		Log.info("Inside Token draw routine: dest location=" + location.x + "," + location.y + ".");
		Log.info("Inside Token draw routine: map sq size size=" + map.squareSizeInFeet + "," + map.squareSizeInFeet + ".");
		Log.info("Inside Token draw routine: tokent size=" + size.getWidth() + "," + size.getHeight() + ".");
		Log.info("Inside Token draw routine: dest size=" + size.getWidth() / map.squareSizeInFeet * map.getsquareSize(location).width + "," + size.getHeight() / map.squareSizeInFeet * map.getsquareSize(location).height + ".");
		GWTCanvas htmlCanvas = map.getHtmlCanvas();
		htmlCanvas.saveContext();
		htmlCanvas.scale(map.getZoomLevel(), map.getZoomLevel());
		htmlCanvas.translate(map.getCurrentOriginX(), map.getCurrentOriginY());
		Dimension sizeInMapUnits = getSizeInMapUnits();
		htmlCanvas.saveContext();
		if (isSelected())
		{
			htmlCanvas.setGlobalAlpha(0.5);
		}
		htmlCanvas.drawImage(ImageElement.as(image.getElement()), 0,0, image.getWidth(), image.getHeight(), location.x, location.y,
				sizeInMapUnits.getWidth(), sizeInMapUnits.getHeight());
		htmlCanvas.restoreContext();
		if (isSelected())
		{
			// TODO: Write text indicating who has selected the token
		}
		htmlCanvas.restoreContext();
	}

	public Dimension getSizeInFeet()
	{
		return size;
	}

	public void setSizeInFeet(Dimension size)
	{
		this.size = size;
	}
	public Dimension getSizeInMapUnits()
	{
		return new Dimension(Math.round(Double.valueOf(size.getWidth()).floatValue() / map.squareSizeInFeet * map.getsquareSize(location).width), Math.round(Double.valueOf(size.getHeight()).floatValue() / map.squareSizeInFeet * map.getsquareSize(location).height));
	}

	public void setSizeInMapUnits(Dimension size)
	{
		this.size = size;
	}

	public Point getLocation()
	{
		return location;
	}

	public void setLocation(Point location)
	{
		this.location = location;
	}
	
	public boolean isPointContained(Point p)
	{
		Point location = getLocation();
		Dimension size = getSizeInMapUnits(); 
		Log.info("Token at " + location.x + "," + location.y + " and " + (location.x + size.width) + "," + (location.y + size.height) + ".");
		return (  p.x >= location.x && p.x <= location.x + size.width 
		   && p.y >= location.y && p.y <= location.y + size.height);
	}

	public boolean isSelected()
	{
		return selectedBy != null;
	}

	public void setSelected(String selectedBy)
	{
		this.selectedBy = selectedBy;
	}
	
	public void setDeSelected()
	{
		this.selectedBy = null;
	}

}
